From fc0f1654a56d2247728a766f43e72ff169704888 Mon Sep 17 00:00:00 2001
From: Owen Jacobson <owen@grimoire.ca>
Date: Sat, 15 Feb 2025 15:17:03 -0500
Subject: Hoist global state access out of individual components.

Access to "global" (maybe "external?") state is now handled at the top level of the component hierarchy, in `+page.svelte`, `+layout.svelte`, and their associated scripts. State is otherwise passed down through props, and changes are passed up through callbacks.

This is - hopefully - groundwork for refactoring state management a bit. I wanted to move access to state out to a smaller number of places, so that I have fewer places to update to implement reconnect logic. My broader goal is to make it easier to refactor these kinds of external side effects, as well, though no such changes are in this branch.

This change also makes testing a mile easier, since tests can interact with props and callbacks instead of emulating the whole HTTP request stack and the Pilcrow API. This change removes do-very-little tests.
---
 ui/routes/(app)/ch/[channel]/+page.svelte | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

(limited to 'ui/routes/(app)/ch/[channel]/+page.svelte')

diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index 84cb0ae..8de9859 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -3,10 +3,22 @@
   import { page } from '$app/state';
   import ActiveChannel from '$lib/components/ActiveChannel.svelte';
   import MessageInput from '$lib/components/MessageInput.svelte';
-  import { channelsList, messages } from '$lib/store';
+  import { channelsList, currentUser, logins, messages } from '$lib/store';
+  import * as api from '$lib/apiServer';
 
   let channel = $derived(page.params.channel);
-  let messageRuns = $derived($messages.inChannel(channel));
+  let messageRuns = $derived(
+    $messages.inChannel(channel).map(({ sender, messages }) => {
+      let senderName = $derived($logins.get(sender));
+      let ownMessage = $derived($currentUser !== null && $currentUser.id === sender);
+
+      return {
+        sender: senderName,
+        ownMessage,
+        messages
+      };
+    })
+  );
   let activeChannel;
 
   function inView(parentElement, element) {
@@ -63,13 +75,21 @@
     clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still.
     lastReadCallback = setTimeout(setLastRead, 2 * 1000);
   }
+
+  async function sendMessage(message) {
+    await api.postToChannel(channel, message);
+  }
+
+  async function deleteMessage(id) {
+    await api.deleteMessage(id);
+  }
 </script>
 
 <svelte:window onkeydown={handleKeydown} />
 
 <div class="active-channel" {onscroll} bind:this={activeChannel}>
-  <ActiveChannel {messageRuns} />
+  <ActiveChannel {messageRuns} {deleteMessage} />
 </div>
 <div class="create-message">
-  <MessageInput {channel} />
+  <MessageInput {sendMessage} />
 </div>
-- 
cgit v1.2.3

